Prerrequisitos
Se requiere tener instaladas y cargadas las siguientes paqueterías.
library(tidyverse)
library(tidyquant)
library(plotly)
library(tsibble)
library(readxl)
library(fpp3)
Algunas series de tiempo
Tipo de cambio USD/JPY
Cargamos los datos a R.
usd_jpy <- read_csv("USD_JPY.csv")
Missing column names filled in: 'X1' [1]Parsed with column specification:
cols(
X1 = col_double(),
TimeStamp = col_datetime(format = ""),
Open = col_double(),
High = col_double(),
Low = col_double(),
Close = col_double()
)
Gráfica de tiempo
p <- usd_jpy %>%
ggplot(aes(x = TimeStamp, y = Close)) +
geom_line()
ggplotly(p)
Gráfica de velas
p <- ggplot(data = usd_jpy, aes(x = TimeStamp, y = Close)) +
geom_candlestick(aes(open = Open, high = High, low = Low, close = Close), colour_up = "darkgreen",colour_down = "red", size = 1)
p

p + coord_x_datetime(xlim = c("2019-07-01","2019-08-01"),
ylim = c(106,109.5))

Horas que pasan los americanos durmiendo
Carga de los datos.
americans <- read_excel("Time Americans Spend Sleeping.xlsx")
americans
Gráfica por tipo de días
p <- americans %>%
filter(Sex == "Both") %>%
ggplot(aes(x = Year, `Avg hrs per day sleeping`,
color = `Age Group`)) +
geom_line() + facet_wrap(~ `Type of Days`, nrow = 1)
ggplotly(p)
Gráfica por tipo de días y Sexo
p <- americans %>%
ggplot(aes(x = Year, `Avg hrs per day sleeping`,
color = `Age Group`)) +
geom_line() + facet_grid(`Type of Days` ~ Sex)
ggplotly(p)
Ventas de autos
car_sales <- tq_get("TOTALNSA", get = "economic.data", from = "1977-01-01")
car_sales
Gráfica de tiempo
p <- car_sales %>%
ggplot(aes(x = date, y = price)) +
geom_line()
ggplotly(p)
El ecosistema tidyverts
Estas paqueterías son parte del tidyverts y utilizan la misma filosofía del tidyverse, pero se especializan en el análisis de series de tiempo.
library(tsibble)
library(feasts)
library(fable)
Descomposición de series de tiempo
us_retail_employment <- us_employment %>%
filter(year(Month) >= 1990, Title == "Retail Trade") %>%
select(-Series_ID)
us_retail_employment
us_retail_employment %>%
autoplot(Employed) +
xlab("Year") + ylab("Persons (thousands)") +
ggtitle("Total employment in US retail")

dcmp <- us_retail_employment %>%
model(STL(Employed))
components(dcmp)
us_retail_employment %>%
autoplot(Employed, color='gray') +
autolayer(components(dcmp), trend, color='red') +
xlab("Year") + ylab("Persons (thousands)") +
ggtitle("Total employment in US retail")

components(dcmp) %>% autoplot() + xlab("Year")

us_retail_employment %>%
autoplot(Employed, color='gray') +
autolayer(components(dcmp), season_adjust, color='blue') +
xlab("Year") + ylab("Persons (thousands)") +
ggtitle("Total employment in US retail")

Descomposición clásica
us_retail_employment %>%
model(classical_decomposition(Employed, type = "additive")) %>%
components() %>%
autoplot() + xlab("Year") +
ggtitle("Classical additive decomposition of total US retail employment")

Descomposición X11
x11_dcmp <- us_retail_employment %>%
model(x11 = feasts:::X11(Employed, type = "additive")) %>%
components()
autoplot(x11_dcmp) + xlab("Year") +
ggtitle("Additive X11 decomposition of US retail employment in the US")

Plot variable not specified, automatically selected `y = Employed`

x11_dcmp %>%
gg_subseries(seasonal)

Descomposición SEATS
seats_dcmp <- us_retail_employment %>%
model(seats = feasts:::SEATS(Employed)) %>%
components()
autoplot(seats_dcmp) + xlab("Year") +
ggtitle("SEATS decomposition of total US retail employment")

Descomposición STL
us_retail_employment %>%
model(STL(Employed ~ trend(window=7) + season(window = "periodic"),
robust = TRUE)) %>%
components() %>%
autoplot()

usd_ts <- usd_jpy %>%
as_tsibble(index = TimeStamp) %>%
fill_gaps() %>% fill(Close)
usd_ts %>%
model(STL(Close)) %>%
components() %>% autoplot()

ge %>%
model(STL(log(GDP))) %>%
components() %>%
autoplot()

LS0tDQp0aXRsZTogIlNlcmllcyBkZSB0aWVtcG8geSBkZXNjb21wb3NpY2nDs24iDQpzdWJ0aXRsZTogIkNsYXNlIDAyIg0KYXV0aG9yOiAiUGFibG8gQmVuYXZpZGVzLUhlcnJlcmEiDQpkYXRlOiAyMDIwLTA2LTAzDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogVFJVRQ0KICAgIHRvY19mbG9hdDogVFJVRQ0KICAgIHRoZW1lOiB1bml0ZWQNCiAgICBoaWdobGlnaHQ6IHRhbmdvDQotLS0NCg0KIyBQcmVycmVxdWlzaXRvcw0KDQpTZSByZXF1aWVyZSB0ZW5lciBpbnN0YWxhZGFzIHkgY2FyZ2FkYXMgbGFzIHNpZ3VpZW50ZXMgcGFxdWV0ZXLDrWFzLg0KDQpgYGB7ciBwa2dzLCBtZXNzYWdlPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHRpZHlxdWFudCkNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeSh0c2liYmxlKQ0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KGZwcDMpDQpgYGANCg0KIyBBbGd1bmFzIHNlcmllcyBkZSB0aWVtcG8NCg0KIyMgVGlwbyBkZSBjYW1iaW8gVVNEL0pQWQ0KDQpDYXJnYW1vcyBsb3MgZGF0b3MgYSAqKlIqKi4NCg0KYGBge3J9DQp1c2RfanB5IDwtIHJlYWRfY3N2KCJVU0RfSlBZLmNzdiIpDQp1c2RfanB5DQpgYGANCg0KIyMjIEdyw6FmaWNhIGRlIHRpZW1wbw0KDQpgYGB7cn0NCnAgPC0gdXNkX2pweSAlPiUgDQogIGdncGxvdChhZXMoeCA9IFRpbWVTdGFtcCwgeSA9IENsb3NlKSkgKw0KICBnZW9tX2xpbmUoKQ0KDQpnZ3Bsb3RseShwKQ0KYGBgDQoNCiMjIyBHcsOhZmljYSBkZSB2ZWxhcw0KDQpgYGB7cn0NCnAgPC0gZ2dwbG90KGRhdGEgPSB1c2RfanB5LCBhZXMoeCA9IFRpbWVTdGFtcCwgeSA9IENsb3NlKSkgKw0KICBnZW9tX2NhbmRsZXN0aWNrKGFlcyhvcGVuID0gT3BlbiwgaGlnaCA9IEhpZ2gsIGxvdyA9IExvdywgY2xvc2UgPSBDbG9zZSksIGNvbG91cl91cCA9ICJkYXJrZ3JlZW4iLGNvbG91cl9kb3duID0gInJlZCIsIHNpemUgPSAxKQ0KcA0KDQpwICsgY29vcmRfeF9kYXRldGltZSh4bGltID0gYygiMjAxOS0wNy0wMSIsIjIwMTktMDgtMDEiKSwgDQogICAgICAgICAgICAgICAgICAgICB5bGltID0gYygxMDYsMTA5LjUpKQ0KYGBgDQoNCiMjIEhvcmFzIHF1ZSBwYXNhbiBsb3MgYW1lcmljYW5vcyBkdXJtaWVuZG8NCg0KQ2FyZ2EgZGUgbG9zIGRhdG9zLg0KDQpgYGB7cn0NCmFtZXJpY2FucyA8LSByZWFkX2V4Y2VsKCJUaW1lIEFtZXJpY2FucyBTcGVuZCBTbGVlcGluZy54bHN4IikNCmFtZXJpY2Fucw0KYGBgDQoNCiMjIyBHcsOhZmljYSBwb3IgdGlwbyBkZSBkw61hcw0KDQpgYGB7cn0NCnAgPC0gYW1lcmljYW5zICU+JSANCiAgZmlsdGVyKFNleCA9PSAiQm90aCIpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gWWVhciwgYEF2ZyBocnMgcGVyIGRheSBzbGVlcGluZ2AsIA0KICAgICAgICAgICAgIGNvbG9yID0gYEFnZSBHcm91cGApKSArDQogIGdlb21fbGluZSgpICsgZmFjZXRfd3JhcCh+IGBUeXBlIG9mIERheXNgLCBucm93ID0gMSkNCg0KZ2dwbG90bHkocCkNCmBgYA0KDQojIyMgR3LDoWZpY2EgcG9yIHRpcG8gZGUgZMOtYXMgeSBTZXhvDQoNCmBgYHtyfQ0KcCA8LSBhbWVyaWNhbnMgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBZZWFyLCBgQXZnIGhycyBwZXIgZGF5IHNsZWVwaW5nYCwgDQogICAgICAgICAgICAgY29sb3IgPSBgQWdlIEdyb3VwYCkpICsNCiAgZ2VvbV9saW5lKCkgKyBmYWNldF9ncmlkKGBUeXBlIG9mIERheXNgIH4gU2V4KQ0KDQpnZ3Bsb3RseShwKQ0KYGBgDQoNCg0KIyMgVmVudGFzIGRlIGF1dG9zDQoNCmBgYHtyfQ0KY2FyX3NhbGVzIDwtIHRxX2dldCgiVE9UQUxOU0EiLCBnZXQgPSAiZWNvbm9taWMuZGF0YSIsIGZyb20gPSAiMTk3Ny0wMS0wMSIpDQpjYXJfc2FsZXMNCmBgYA0KDQojIyMgR3LDoWZpY2EgZGUgdGllbXBvDQoNCmBgYHtyfQ0KcCA8LSBjYXJfc2FsZXMgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBkYXRlLCB5ID0gcHJpY2UpKSArIA0KICBnZW9tX2xpbmUoKQ0KDQpnZ3Bsb3RseShwKQ0KYGBgDQoNCiMgVGlwb3MgZGUgYWp1c3Rlcy90cmFuc2Zvcm1hY2lvbmVzDQoNCiMjIEFqdXN0ZXMgcG9yIHBvYmxhY2nDs24NCg0KVG9tYXJlbW9zIGxhIHRhYmxhIGBnbG9iYWxfZWNvbm9teWAgeSB2YW1vcyBhIGZpbHRyYXJsYSBwYXJhIHF1ZWRhcm5vcyBjb24gY3VhdHJvIHBhw61zZXMgeSBncmFmaWNhciBlbCBQSUIgeSBlbCBQSUIgY29uIGVzY2FsYSBsb2dhcsOtdG1pY2EuDQoNCmBgYHtyfQ0KZ2UgPC0gZ2xvYmFsX2Vjb25vbXkgJT4lIA0KICBmaWx0ZXIoQ291bnRyeSAlaW4lIGMoIk1leGljbyIsICJJY2VsYW5kIiwgIkF1c3RyYWxpYSIsICJDb2xvbWJpYSIpKQ0KDQpwMyA8LSBnZ3Bsb3QoZ2UpICsgYWVzKHggPSBZZWFyLCB5ID0gR0RQLCBjb2xvciA9IENvdW50cnkpICsgDQogIGdlb21fbGluZShzaXplID0gMSkNCg0KcDMNCmBgYA0KUmV2aXNhbmRvIGxhIMO6bHRpbWEgcG9ibGFjacOzbiByZWdpc3RyYWRhIGRlIGNhZGEgcGHDrXMuDQoNCmBgYHtyfQ0KZ2UgJT4lIA0KICBmaWx0ZXIoWWVhciA9PSAyMDE3KSAlPiUgDQogIGFycmFuZ2UoZGVzYyhQb3B1bGF0aW9uKSkNCmBgYA0KDQpWZW1vcyBxdWUgZXhpc3RlIHVuYSBncmFuIGRpZmVyZW5jaWEgZW4gbGEgcG9ibGFjacOzbiBkZSBlc3RvcyBwYcOtc2VzLiBQYXJhIHBvZGVyIGNvbXBhcmFyIGVsIFBJQiBlbnRyZSBlbGxvcywgc2Vyw61hIG1lam9yIHJlYWxpemFyIHVuICoqYWp1c3RlIHBvciBwb2JsYWNpw7NuKiogeSByZXZpc2FyIGxhIHZhcmlhYmxlICpQSUIgcGVyIGPDoXBpdGEqLg0KDQpgYGB7cn0NCmdlIDwtIGdsb2JhbF9lY29ub215ICU+JSANCiAgZmlsdGVyKENvdW50cnkgJWluJSBjKCJBdXN0cmFsaWEiLCAiTWV4aWNvIiwgIkljZWxhbmQiLCAiQ29sb21iaWEiKSkNCg0KcDQgPC0gZ2dwbG90KGdlKSArIGFlcyh4ID0gWWVhciwgeSA9IEdEUCAvIFBvcHVsYXRpb24sIGNvbG9yID0gQ291bnRyeSkgKw0KICBnZW9tX2xpbmUoc2l6ZSA9IDEpICsgeWxhYigiR0RQIHBlciBjYXBpdGEiKQ0KDQpwNA0KYGBgDQoNCiMjIFRyYW5zZm9ybWFjaW9uZXMgbWF0ZW3DoXRpY2FzDQoNCkNvbcO6bm1lbnRlIHNlIHBvZHLDoW4gbGxldmFyIGEgY2FibyB0cmFuc2Zvcm1hY2lvbmVzIGxvZ2Fyw610bWljYXMuDQoNCmBgYHtyfQ0KcDMgKyBzY2FsZV95X2xvZzEwKCkNCmBgYA0KDQoNCiMjIEFqdXN0ZXMgcG9yIGluZmxhY2nDs24NCg0KVG9tYXJlbW9zIGxhIHRhYmxhIHByZWNhcmdhZGEgYGF1c19yZXRhaWxgIHkgc2VsZWNjaW9uYXJlbW9zIGxhIGluZHVzdHJpYSBkZSBpbXByZXNpw7NuLiBSZXN1bWlyZW1vcyBsb3MgZGF0b3MgZGUgbWFuZXJhIGFudWFsIHkgY29tcGFyYXJlbW9zIGxhcyBncsOhZmljYXMgZGUgbGEgc2VyaWUgZW4gcHJlY2lvcyBjb3JyaWVudGVzIHkgYWp1c3RhZG9zIHBvciBpbmZsYWNpw7NuIChvIGEgKnByZWNpb3MgY29uc3RhbnRlcyopLg0KDQpgYGB7cn0NCnByaW50X3JldGFpbCA8LSBhdXNfcmV0YWlsICU+JQ0KICBmaWx0ZXIoSW5kdXN0cnkgPT0gIk5ld3NwYXBlciBhbmQgYm9vayByZXRhaWxpbmciKSAlPiUNCiAgZ3JvdXBfYnkoSW5kdXN0cnkpICU+JQ0KICBpbmRleF9ieShZZWFyID0geWVhcihNb250aCkpICU+JQ0KICBzdW1tYXJpc2UoVHVybm92ZXIgPSBzdW0oVHVybm92ZXIpKQ0KYXVzX2Vjb25vbXkgPC0gZ2xvYmFsX2Vjb25vbXkgJT4lDQogIGZpbHRlcihDb2RlID09ICJBVVMiKQ0KcHJpbnRfcmV0YWlsICU+JQ0KICBsZWZ0X2pvaW4oYXVzX2Vjb25vbXksIGJ5ID0gIlllYXIiKSAlPiUNCiAgbXV0YXRlKEFkanVzdGVkX3R1cm5vdmVyID0gVHVybm92ZXIgLyBDUEkpICU+JQ0KICBnYXRoZXIoIlR5cGUiLCAiVHVybm92ZXIiLCBUdXJub3ZlciwgQWRqdXN0ZWRfdHVybm92ZXIsIGZhY3Rvcl9rZXkgPSBUUlVFKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gWWVhciwgeSA9IFR1cm5vdmVyKSkgKw0KICAgIGdlb21fbGluZSgpICsNCiAgICBmYWNldF9ncmlkKHZhcnMoVHlwZSksIHNjYWxlcyA9ICJmcmVlX3kiKSArDQogICAgeGxhYigiWWVhcnMiKSArIHlsYWIoTlVMTCkgKw0KICAgIGdndGl0bGUoIlR1cm5vdmVyIGZvciB0aGUgQXVzdHJhbGlhbiBwcmludCBtZWRpYSBpbmR1c3RyeSIpDQpgYGANCg0KIyBFbCBlY29zaXN0ZW1hIHRpZHl2ZXIqdHMqDQoNCkVzdGFzIHBhcXVldGVyw61hcyBzb24gcGFydGUgZGVsIHRpZHl2ZXIqdHMqIHkgdXRpbGl6YW4gbGEgbWlzbWEgZmlsb3NvZsOtYSBkZWwgYHRpZHl2ZXJzZWAsIHBlcm8gc2UgZXNwZWNpYWxpemFuIGVuIGVsIGFuw6FsaXNpcyBkZSBzZXJpZXMgZGUgdGllbXBvLg0KDQpgYGB7cn0NCmxpYnJhcnkodHNpYmJsZSkNCmxpYnJhcnkoZmVhc3RzKQ0KbGlicmFyeShmYWJsZSkNCmBgYA0KDQojIyBUcmFuc2Zvcm1hY2lvbmVzIGRlIEJveC1Db3gNCg0KT3RyYSBmYW1pbGlhIGRlIHRyYW5zZm9ybWFjaW9uZXMsIHF1ZSBkZXBlbmRlIGRlIHVuIHBhcsOhbWV0cm8gJFxsYW1iZGEkIHBhcmEgZXNjb2dlciBlbCB0aXBvIGRlIHRyYW5zZm9ybWFjacOzbiBhIHJlYWxpemFyLiBQYXJhIGVqZW1wbGlmaWNhcmxvLCB0b21hbW9zIGxvcyBkYXRvcyBwcmVjYXJnYWRvcyBgYXVzX3Byb2R1Y3Rpb25gLg0KDQpgYGB7cn0NCmF1c19wcm9kdWN0aW9uDQpgYGANCg0KR3JhZmljYXIgbGEgcHJvZHVjY2nDs24gZGUgZ2FzLg0KDQpgYGB7cn0NCmF1c19wcm9kdWN0aW9uICU+JSBhdXRvcGxvdChHYXMpDQpgYGANCg0KUXVlcmVtb3MgKmVzdGFiaWxpemFyIGxhIHZhcmlhbnphKiB5IHVuYSB0cmFuc2Zvcm1hY2nDs24gbG9nYXLDrXRtaWNhIChvIEJveC1Db3ggY29uICRcbGFtYmRhID0gMCQpIHBhcmVjZSBubyBzZXIgc3VmaWNpZW50ZToNCg0KYGBge3J9DQphdXNfcHJvZHVjdGlvbiAlPiUgYXV0b3Bsb3QobG9nKEdhcykpDQpgYGANCg0KT2J0ZW5lbW9zIGxhICoqY2FyYWN0ZXLDrXN0aWNhIGRlIEd1ZXJyZXJvKiogcGFyYSBkZWNpZGlyIGVsIHZhbG9yIMOzcHRpbW8gZGUgJFxsYW1iZGEkLg0KDQpgYGB7cn0NCihsYW1iZGEgPC0gYXVzX3Byb2R1Y3Rpb24gJT4lDQogIGZlYXR1cmVzKEdhcywgZmVhdHVyZXMgPSBndWVycmVybykgJT4lDQogIHB1bGwobGFtYmRhX2d1ZXJyZXJvKSkNCmBgYA0KDQpQb2RlbW9zIGFwbGljYXIgbGEgdHJhbnNmb3JtYWNpw7NuIGRpcmVjdG8gZW4gZWwgYGF1dG9wbG90YC4NCg0KYGBge3J9DQphdXNfcHJvZHVjdGlvbiAlPiUgYXV0b3Bsb3QoYm94X2NveChHYXMsIGxhbWJkYSkpDQpgYGANCg0KIyMgRGVzY29tcG9zaWNpw7NuIGRlIHNlcmllcyBkZSAgdGllbXBvDQoNCmBgYHtyfQ0KdXNfcmV0YWlsX2VtcGxveW1lbnQgPC0gdXNfZW1wbG95bWVudCAlPiUNCiAgZmlsdGVyKHllYXIoTW9udGgpID49IDE5OTAsIFRpdGxlID09ICJSZXRhaWwgVHJhZGUiKSAlPiUNCiAgc2VsZWN0KC1TZXJpZXNfSUQpDQoNCnVzX3JldGFpbF9lbXBsb3ltZW50DQoNCnVzX3JldGFpbF9lbXBsb3ltZW50ICU+JQ0KICBhdXRvcGxvdChFbXBsb3llZCkgKw0KICB4bGFiKCJZZWFyIikgKyB5bGFiKCJQZXJzb25zICh0aG91c2FuZHMpIikgKw0KICBnZ3RpdGxlKCJUb3RhbCBlbXBsb3ltZW50IGluIFVTIHJldGFpbCIpDQpgYGANCg0KYGBge3J9DQpkY21wIDwtIHVzX3JldGFpbF9lbXBsb3ltZW50ICU+JQ0KICBtb2RlbChTVEwoRW1wbG95ZWQpKQ0KDQpjb21wb25lbnRzKGRjbXApDQpgYGANCg0KYGBge3J9DQp1c19yZXRhaWxfZW1wbG95bWVudCAlPiUNCiAgYXV0b3Bsb3QoRW1wbG95ZWQsIGNvbG9yPSdncmF5JykgKw0KICBhdXRvbGF5ZXIoY29tcG9uZW50cyhkY21wKSwgdHJlbmQsIGNvbG9yPSdyZWQnKSArDQogIHhsYWIoIlllYXIiKSArIHlsYWIoIlBlcnNvbnMgKHRob3VzYW5kcykiKSArDQogIGdndGl0bGUoIlRvdGFsIGVtcGxveW1lbnQgaW4gVVMgcmV0YWlsIikNCmBgYA0KDQpgYGB7cn0NCmNvbXBvbmVudHMoZGNtcCkgJT4lIGF1dG9wbG90KCkgKyB4bGFiKCJZZWFyIikNCmBgYA0KDQpgYGB7cn0NCnVzX3JldGFpbF9lbXBsb3ltZW50ICU+JQ0KICBhdXRvcGxvdChFbXBsb3llZCwgY29sb3I9J2dyYXknKSArDQogIGF1dG9sYXllcihjb21wb25lbnRzKGRjbXApLCBzZWFzb25fYWRqdXN0LCBjb2xvcj0nYmx1ZScpICsNCiAgeGxhYigiWWVhciIpICsgeWxhYigiUGVyc29ucyAodGhvdXNhbmRzKSIpICsNCiAgZ2d0aXRsZSgiVG90YWwgZW1wbG95bWVudCBpbiBVUyByZXRhaWwiKQ0KYGBgDQojIyMgRGVzY29tcG9zaWNpw7NuIGNsw6FzaWNhDQoNCmBgYHtyfQ0KdXNfcmV0YWlsX2VtcGxveW1lbnQgJT4lDQogIG1vZGVsKGNsYXNzaWNhbF9kZWNvbXBvc2l0aW9uKEVtcGxveWVkLCB0eXBlID0gImFkZGl0aXZlIikpICU+JQ0KICBjb21wb25lbnRzKCkgJT4lDQogIGF1dG9wbG90KCkgKyB4bGFiKCJZZWFyIikgKw0KICBnZ3RpdGxlKCJDbGFzc2ljYWwgYWRkaXRpdmUgZGVjb21wb3NpdGlvbiBvZiB0b3RhbCBVUyByZXRhaWwgZW1wbG95bWVudCIpDQpgYGANCg0KIyMjIERlc2NvbXBvc2ljacOzbiBYMTENCg0KYGBge3J9DQp4MTFfZGNtcCA8LSB1c19yZXRhaWxfZW1wbG95bWVudCAlPiUNCiAgbW9kZWwoeDExID0gZmVhc3RzOjo6WDExKEVtcGxveWVkLCB0eXBlID0gImFkZGl0aXZlIikpICU+JQ0KICBjb21wb25lbnRzKCkNCg0KYXV0b3Bsb3QoeDExX2RjbXApICsgeGxhYigiWWVhciIpICsNCiAgZ2d0aXRsZSgiQWRkaXRpdmUgWDExIGRlY29tcG9zaXRpb24gb2YgVVMgcmV0YWlsIGVtcGxveW1lbnQgaW4gdGhlIFVTIikNCmBgYA0KDQpgYGB7cn0NCngxMV9kY21wICU+JSANCiAgZ2dfc2Vhc29uKCkNCmBgYA0KDQpgYGB7cn0NCngxMV9kY21wICU+JSANCiAgZ2dfc3Vic2VyaWVzKHNlYXNvbmFsKQ0KYGBgDQojIyMgRGVzY29tcG9zaWNpw7NuIFNFQVRTDQoNCmBgYHtyfQ0Kc2VhdHNfZGNtcCA8LSB1c19yZXRhaWxfZW1wbG95bWVudCAlPiUNCiAgbW9kZWwoc2VhdHMgPSBmZWFzdHM6OjpTRUFUUyhFbXBsb3llZCkpICU+JQ0KICBjb21wb25lbnRzKCkNCmF1dG9wbG90KHNlYXRzX2RjbXApICsgeGxhYigiWWVhciIpICsNCiAgZ2d0aXRsZSgiU0VBVFMgZGVjb21wb3NpdGlvbiBvZiB0b3RhbCBVUyByZXRhaWwgZW1wbG95bWVudCIpDQpgYGANCg0KIyMjIERlc2NvbXBvc2ljacOzbiBTVEwNCg0KYGBge3J9DQp1c19yZXRhaWxfZW1wbG95bWVudCAlPiUNCiAgbW9kZWwoU1RMKEVtcGxveWVkIH4gdHJlbmQod2luZG93PTcpICsgc2Vhc29uKHdpbmRvdyA9ICJwZXJpb2RpYyIpLA0KICAgIHJvYnVzdCA9IFRSVUUpKSAlPiUNCiAgY29tcG9uZW50cygpICU+JQ0KICBhdXRvcGxvdCgpDQpgYGANCg0KYGBge3J9DQp1c2RfdHMgPC0gdXNkX2pweSAlPiUNCiAgYXNfdHNpYmJsZShpbmRleCA9IFRpbWVTdGFtcCkgJT4lIA0KICBmaWxsX2dhcHMoKSAlPiUgZmlsbChDbG9zZSkNCg0KdXNkX3RzICU+JSANCiAgbW9kZWwoU1RMKENsb3NlKSkgJT4lIA0KICBjb21wb25lbnRzKCkgJT4lIGF1dG9wbG90KCkNCmBgYA0KYGBge3J9DQpnZSAlPiUgDQogIG1vZGVsKFNUTChsb2coR0RQKSkpICU+JSANCiAgY29tcG9uZW50cygpICU+JSANCiAgYXV0b3Bsb3QoKQ0KYGBgDQoNCg0KDQo=